using System;
using System.Collections.Generic;
using System.Xml.Linq;
using TEngine;
using TMPro;
using static GameLogic.SocketDefinition;

namespace GameLogic
{
    #region 比赛相关枚举、API cmd定义
    public enum E_ENTER_FAIL
    {
        E_ENTER_SUC = 0,
        E_ENTER_FAIL_ERROR_REQ, // 请求的消息出错（比如长度错误）
        E_ENTER_FAIL_EXIST_IN_AGENT,    // 用户已在某个代理内，不能重复进入
        E_ENTER_FAIL_AGENT_NOT_EXIST,   // 代理不存在
        E_ENTER_FAIL_AGENT_REFUSE,  // 代理拒绝该用户加入（多半是该玩家不在参赛玩家列表中，小概率其它原因）
    };

    public enum E_EXIT_SERVER
    {
        E_EXIT_SERVER_MATCH_END = 0,              // 比赛结束
        E_EXIT_SERVER_KICK_OUT = 1,               // 被踢
        E_EXIT_SERVER_OFFLINE_TIME_OUT = 2,       // 断线超时未重连
        E_EXIT_SERVER_MAINTENANCE = 3,            // 服务维护
        E_EXIT_SERVER_INFO_ALREADY_EXISTS = 254,  // 已存在游戏信息（不处理）
        E_EXIT_SERVER_AGENT_BREAK = 255           // 中转使用，与游戏服断线
    };

    public enum E_USER_PAY : uint
    {
        E_USER_PAY_SUCCESS,             // 成功
        E_USER_PAY_NO_MONEY,            // 银子不足
        E_USER_PAY_UNKNOW = 0xffffffff, // 未知错误
    };

    public enum MATCH_GAME_GENERAL_ERROR
    {
        UNKNOWN,            // 未知
        GETDRESSFAILED,     // 获取个性装扮失败
    }

    /// <summary>
    /// 基础比赛相关的消息ID及包体，约等于比赛服
    /// </summary>
    public enum API_ID_MATCH : uint
    {       
        //进入比赛
        ENTER_MATCH = BS_MSG_GAME_BASE + 0x3,
        //反馈-进入比赛
        ON_ENTER_MATCH = GAME_REF + ENTER_MATCH,
        //退出比赛
        EXIT_MATCH = BS_MSG_GAME_BASE + 0x4,
        //用户离开服务器
        USER_EXIT_SERVER = BS_MSG_GAME_BASE + 0xb,
        /// <summary>
        /// 比赛宕机
        /// </summary>
        MATCH_BREAK_OFF = BS_MSG_GAME_BASE + 0xe,
        /// <summary>
        /// 比赛指令
        /// </summary>
        MATCH_GAME_COMMAND = BS_MSG_GAME_BASE + 0x10,
        //用户退出比赛
        USER_EXIT_GAME = BS_MSG_GAME_BASE + 0x12,
        //用户消费结果（翻翻乐）
        USER_PAY_RESULT = BS_MSG_GAME_BASE + 0x13,
        //请求获取道具列表
        SEND_OPEN_PROP = BS_MSG_GAME_BASE + 0x16,
        //反馈获取道具列表
        ON_SEND_OPEN_PROP = GAME_REF + SEND_OPEN_PROP,
        //使用道具请求
        USE_PROP = BS_MSG_GAME_BASE + 0x17,
        //反馈使用道具请求
        ON_USE_PROP = GAME_REF + USE_PROP,
        //使用道具请求通知
        ON_USE_PROP_NOTICE = BS_MSG_GAME_BASE + 0x18,
        //客户端发送表情(支持给指定玩家发送)
        CHAT_MESSAGE = BS_MSG_GAME_BASE + 0x21,
        //客户端接收互动消息
        ON_CHAT_MESSAGE = BS_MSG_GAME_BASE + 0x22,
        //请求翻翻乐底分
        ASK_FLOP_BASE_SCORE = BS_MSG_GAME_BASE + 0x26,
        //反馈-请求翻翻乐底分
        ON_FLOP_BASE_SCORE = GAME_REF + ASK_FLOP_BASE_SCORE,
        // 新比赛服通用错误
        ON_GENERAL_ERROR = GAME_REF + (BS_MSG_GAME_BASE + 0x27),
        //比赛内玩家装扮信息
        PLAYER_DRESS_INFO_GAME = BS_MSG_GAME_BASE + 0x28,
        //回合信息
        GAME_ROUND_INFO = BS_MSG_GAME_BASE + 0x29,
        //复合包
        COMPOSITE_PACKAGE = BS_MSG_GAME_BASE + 0x2f,
        //数值推送
        DATA_PUSH_INFO = BS_MSG_GAME_BASE + 0x31,
        //回合结束统计信息
        ON_GET_ROUND_END_STATISTICS_DATA = BS_MSG_GAME_BASE + 0x46,
        /// <summary>
        /// 透传JSON数据
        /// </summary>
        TRANSPARNET_DATA = 0x7400,
        /// <summary>
        /// 获取玩家信息
        /// </summary>
        GET_PLAYER_INFO = 0x4020,
        /// <summary>
        /// 获取桌上的玩家状态数据
        /// </summary>
        GET_PLAYER_STATE = 0x4021
    }
    #endregion

    #region 接收到的包
    /// <summary>
    /// 进入比赛反馈数据包
    /// </summary>
    public class OnEnterMatchPacket : ReceivePack
    {
        public E_ENTER_FAIL reason;
        public uint id = 0;

        public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
        {
            (D_TYPE.INT, nameof(reason)),
            (D_TYPE.DWORD, nameof(id))
        };

        /// <summary>
        /// 是否已失效。判断标准为当前包的id值存在且不等于最新的enterMatchPackID
        /// </summary>
        public bool Invalid 
        {
            get => (id != 0 && id != MatchManager.Instance.crtEnterMatchPackTag);
        }
    }

    /// <summary>
    /// 用户离开服务器通知数据包
    /// </summary>
    public class UserExitServerPacket : ReceivePack
    {
        public E_EXIT_SERVER exitReason;

        public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
        {
            (D_TYPE.DWORD, nameof(exitReason))
        };
    }

    /// <summary>
    /// 比赛宕机通知数据包
    /// </summary>
    public class MatchBreakOffPacket : ReceivePack
    {

    }

    /// <summary>
    /// 用户退出比赛通知数据包
    /// </summary>
    public class UserExitGamePacket : ReceivePack
    {
        public uint userID;
        public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
        {
            (D_TYPE.DWORD, nameof(userID))
        };
    }

    /// <summary>
    /// 用户消费结果(翻翻乐)数据包
    /// </summary>
    public class UserPayResultPacket : ReceivePack
    {
        public uint userID;
        public E_USER_PAY result;

        public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
        {
            (D_TYPE.DWORD, nameof(userID)),
            (D_TYPE.DWORD, nameof(result))
        };
    }

    ///// <summary>
    ///// 获取道具列表反馈数据包
    ///// </summary>
    //public class OnSendOpenPropPacket : ReceivePack
    //{
    //    public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
    //    {
    //    };

    //    public override ReceivePack Read(byte[] data)
    //    {
    //        return this;
    //    }
    //}

    ///// <summary>
    ///// 使用道具反馈数据包
    ///// </summary>
    //public class OnUsePropPacket : ReceivePack
    //{
    //    public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
    //    {
    //    };

    //    public override ReceivePack Read(byte[] data)
    //    {
    //        return this;
    //    }
    //}

    ///// <summary>
    ///// 使用道具通知数据包
    ///// </summary>
    //public class OnUsePropNoticePacket : ReceivePack
    //{
    //    public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
    //    {
    //    };

    //    public override ReceivePack Read(byte[] data)
    //    {
    //        return this;
    //    }
    //}

    ///// <summary>
    ///// 客户端发送表情数据包
    ///// </summary>
    //public class ChatMessagePacket : ReceivePack
    //{
    //    public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
    //    {
    //    };

    //    public override ReceivePack Read(byte[] data)
    //    {
    //        return this;
    //    }
    //}

    ///// <summary>
    ///// 客户端接收互动消息数据包
    ///// </summary>
    //public class OnChatMessagePacket : ReceivePack
    //{
    //    public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
    //    {
    //    };

    //    public override ReceivePack Read(byte[] data)
    //    {
    //        return this;
    //    }
    //}

    ///// <summary>
    ///// 翻翻乐底分反馈数据包
    ///// </summary>
    //public class OnFlopBaseScorePacket : ReceivePack
    //{
    //    public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
    //    {
    //    };

    //    public override ReceivePack Read(byte[] data)
    //    {
    //        return this;
    //    }
    //}

    /// <summary>
    /// 比赛服通用错误数据包
    /// </summary>
    public class OnGeneralErrorPacket : ReceivePack
    {
        public MATCH_GAME_GENERAL_ERROR error;
        public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
        {
            (D_TYPE.DWORD, nameof(error))
        };
    }

    /// <summary>
    /// 比赛内玩家装扮信息数据包
    /// </summary>
    public class PlayerDressInfoGamePacket : ReceivePack
    {
        public uint userID;
        public SuffixIdxReceive suf = new SuffixIdxReceive();
        public string dressInfo;
        public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
        {
            (D_TYPE.DWORD, nameof(userID)),
            (suf, nameof(suf))
        };

        public override ReceivePack Read(byte[] data)
        {
            base.Read(data);
            (int offset, int size) = ((int)(suf.offset - NewHeadReceive.Size), (int)suf.size);
            if (size != 0)
            {
                var reader = new BinaryPacketReader(data[offset..(offset + size)]);
                dressInfo = reader.ReadString(size);
            }
            return this;
        }
    }

    /// <summary>
    /// 回合信息数据包
    /// </summary>
    public class GameRoundInfoPacket : ReceivePack
    {
        public bool isPlaying;
        public uint playerCount;

        public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
        {
            (D_TYPE.BOOL8, nameof(isPlaying)),
            (D_TYPE.DWORD, nameof(playerCount))
        };
    }

    ///// <summary>
    ///// 复合数据包
    ///// </summary>
    //public class CompositePackagePacket : ReceivePack
    //{
    //    public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
    //    {
    //    };

    //    public override ReceivePack Read(byte[] data)
    //    {
    //        return this;
    //    }
    //}

    /// <summary>
    /// 数值推送数据包
    /// </summary>
    public class DataPushInfoPacket : ReceivePack
    {
        public uint userID;
        public SuffixIdxReceive suf = new SuffixIdxReceive();
        public string content;

        public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
        {
            (D_TYPE.DWORD, nameof(userID)),
            (suf, nameof(suf))
        };

        public override ReceivePack Read(byte[] data)
        {
            base.Read(data);
            (int offset, int size) = ((int)(suf.offset - NewHeadReceive.Size), (int)suf.size);
            if (size != 0)
            {
                var reader = new BinaryPacketReader(data[offset..(offset + size)]);
                content = reader.ReadString(size);
            }
            return this;
        }
    }

    ///// <summary>
    ///// 回合结束统计信息数据包
    ///// </summary>
    //public class OnGetRoundEndStatisticsDataPacket : ReceivePack
    //{
    //    public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
    //    {
    //    };

    //    public override ReceivePack Read(byte[] data)
    //    {
    //        return this;
    //    }
    //}

    /// <summary>
    /// 透传数据
    /// </summary>
    public class TransparentDataPacket : ReceivePack
    {
        public SuffixIdxReceive suffixIdx = new SuffixIdxReceive();
        public string rawStr;

        public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
        {
            (suffixIdx, nameof(suffixIdx))
        };

        public override ReceivePack Read(byte[] data)
        {
            base.Read(data);
            (int offset, int size) = ((int)(suffixIdx.offset - NewHeadReceive.Size), (int)suffixIdx.size);
            if (size != 0)
            {
                var reader = new BinaryPacketReader(data[offset..(offset + size)]);
                rawStr = reader.ReadString(size);
            }
            Log.Warning("TODO 还需要把字符串转为对象使用");
            return this;
        }

        //JsonDataBase
    }

    public class GetPlayerInfoListPakcet : ReceivePack
    {
        public List<PlayerVO> userList = new List<PlayerVO>();

        public override ReceivePack Read(byte[] data)
        {
            base.Read(data);
            var reader = new BinaryPacketReader(data);
            while (reader.HasRemainingData())
            {
                uint len = (uint)reader.ReadData(D_TYPE.DWORD);
                GetPlayerInfoPacket p = new GetPlayerInfoPacket();
                reader.ReadDataPack(p);
                userList.Add(p.player);
            }
            return this;
        }
    }

    public class GetPlayerInfoPacket : ReceivePack
    {
        public short idx;
        public uint uID;

        public PlayerVO player;

        public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
        {
            (D_TYPE.SHORT, nameof(idx)),
            (D_TYPE.UINT, nameof(uID))
        };

        public override ReceivePack Read(byte[] data)
        {
            base.Read(data);
            player = PlayerVO.Rent();
            ReadUserInfo(data, ref player);
            return this;
        }

        private void ReadUserInfo(byte[] data, ref PlayerVO user)
        {
            var reader = new BinaryPacketReader(data);
            bool bReadString = false;
            while (reader.HasRemainingData())
            {
                short idx = (short)reader.ReadData(D_TYPE.SHORT);
                //如果当前字段的idx在INT表中查到，则表示此字段类型为INT，按INT类型解析
                string keyName = PlayerVO.P_INFO_INT_KEYS[idx];
                if (keyName != null)
                {
                    uint value = (uint)reader.ReadData(D_TYPE.UINT);
                    var property = user.GetType().GetField(keyName);
                    if (property != null)
                    {
                        property.SetValue(user, value);
                        return;
                    }
                    else
                    {
                        Log.Error($"ReadUserInfo 找不到id:{idx}字段: {keyName}");
                    }
                }
                else
                {
                    keyName = PlayerVO.P_INFO_STRING_KEYS[idx];
                    if (keyName != null)
                    {
                        bReadString = true;
                        int len = (int)reader.ReadData(D_TYPE.INT);
                        string value = reader.ReadString(len);
                        var property = user.GetType().GetField(keyName);
                        if (property != null)
                        {
                            property.SetValue(user, value);
                            return;
                        }
                        else
                        {
                            Log.Error($"ReadUserInfo 找不到id:{idx}字段: {keyName}");
                        }
                    }
                    else
                    {
                        if (bReadString)
                        {
                            Log.Error($"ReadUserInfo Parse APIReadUserInfo ERROR: idx${idx} cant find match type!");
                            break;
                        }
                        else
                        {
                            reader.ReadData(D_TYPE.UINT);  //保险，如果服务器加了一个新的int，不会报错并且会继续读后面的string
                        }
                    }
                }

            }
        }
    }

    public class GetPlayerStateListPakcet : ReceivePack
    {
        public List<PlayerVO> userList = new List<PlayerVO>();

        public override ReceivePack Read(byte[] data)
        {
            base.Read(data);
            var reader = new BinaryPacketReader(data);
            while (reader.HasRemainingData())
            {
                uint len = (uint)reader.ReadData(D_TYPE.DWORD);
                GetPlayerStatePacket p = new GetPlayerStatePacket();
                reader.ReadDataPack(p);
                userList.Add(p.player);
            }
            return this;
        }
    }

    public class GetPlayerStatePacket : GetPlayerInfoPacket
    {
        public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
        {
            (D_TYPE.UINT, nameof(uID))
        };
    }
    #endregion

    #region 发送的包
    public enum PLAYER_TYPE
    {
        /** 选手 */
        PLAY,
        /** 旁观 */
        WATCH
    }

    /// <summary>
    /// 进入比赛请求数据包
    /// </summary>
    public class EnterMatchPacket : SendPack
    {
        protected override uint GetCmdID() => (uint)API_ID_MATCH.ENTER_MATCH;

        public MatchKeyInfo matchInfo = new MatchKeyInfo();
        public PLAYER_TYPE userType = PLAYER_TYPE.PLAY;
        public uint GSIP;
        public uint GSPort;
        public uint id;
     
        public EnterMatchPacket()
        {
            id = ++MatchManager.Instance.crtEnterMatchPackTag;
        }

        public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
        {
            (matchInfo, nameof(matchInfo)),
            (D_TYPE.BYTE, nameof(userType)),
            (D_TYPE.DWORD, nameof(GSIP)),
            (D_TYPE.DWORD, nameof(GSPort)),
            (D_TYPE.DWORD, nameof(id))
        };
    }

    public class MatchKeyInfo : SendPack
    {
        protected override uint GetCmdID() => (uint)API_ID_BASE.NONE;

        /// <summary>
        /// 比赛产品ID
        /// </summary>
        public uint productID;

        /// <summary>
        /// 锦标赛ID
        /// </summary>
        public uint tourneyID;

        /// <summary>
        /// 开赛时间
        /// </summary>
        public uint matchTime;

        /// <summary>
        /// 比赛ID
        /// </summary>
        public uint matchID;

        /// <summary>
        /// 阶段ID
        /// </summary>
        public ushort phaseID;

        /// <summary>
        /// 轮次ID,第几轮(瑞士移位)
        /// </summary>
        public ushort boutID;

        /// <summary>
        /// 分组ID
        /// </summary>
        public ushort stageID;

        /// <summary>
        /// 回合ID
        /// </summary>
        public uint roundID;

        /// <summary>
        /// 桌号（第几桌）,作为补充信息，供部分比赛使用
        /// </summary>
        public uint tableID;

        /// <summary>
        /// 游戏ID
        /// </summary>
        public uint gameID;

        public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
        {
            (D_TYPE.DWORD, nameof(productID)),
            (D_TYPE.DWORD, nameof(tourneyID)),
            (D_TYPE.DWORD, nameof(matchTime)),
            (D_TYPE.DWORD, nameof(matchID)),
            (D_TYPE.WORD, nameof(phaseID)),
            (D_TYPE.WORD, nameof(boutID)),
            (D_TYPE.WORD, nameof(stageID)),
            (D_TYPE.DWORD, nameof(roundID)),
            (D_TYPE.DWORD, nameof(tableID)),
            (D_TYPE.DWORD, nameof(gameID))
        };
    }

    /// <summary>
    /// 退出比赛数据包
    /// </summary>
    public class ExitMatchPacket : SendPack
    {
        protected override uint GetCmdID() => (uint)API_ID_MATCH.EXIT_MATCH;

        public MatchKeyInfo matchInfo = new MatchKeyInfo();
        public uint bForceExit = 0;

        public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
        {
            (matchInfo, nameof(matchInfo)),
            (D_TYPE.DWORD, nameof(bForceExit)),
        };
    }

    ///// <summary>
    ///// 请求获取道具列表数据包
    ///// </summary>
    //public class SendOpenPropPacket : SendPack
    //{
    //    protected override uint GetCmdID() => (uint)API_ID_MATCH.EXIT_MATCH;

    //    public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
    //    {


    //    };
    //}

    ///// <summary>
    ///// 请求翻翻乐底分数据包
    ///// </summary>
    //public class AskFlopBaseScorePacket : SendPack
    //{
    //    protected override uint GetCmdID() => (uint)API_ID_MATCH.EXIT_MATCH;
    //    public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
    //    {
    //    };

    //}

    ///// <summary>
    ///// 使用道具请求数据包
    ///// </summary>
    //public class UsePropPacket : SendPack
    //{
    //    protected override uint GetCmdID() => (uint)API_ID_MATCH.USE_PROP;

    //    public override List<(TypeInfo type, string propertyName)> PropertySequence => new()
    //    {

    //    };
    //}


    #endregion
}